import mongoose from 'mongoose'
import bcrypt from 'bcryptjs'
const Schema = mongoose.Schema

const saltRounds = 10
const MAX_LOGIN_AttAMPTS = 10
const LOCK_TIEM = 2 * 60 * 60 * 1000

const UserSchema = new Schema({
  email: String,
  password: String,
  hashed_password: String,
  loginAttempts: Number,
  lockTime: Number,

  openid: [String],
  unionid: String,
  nickname: String,
  address: String,
  province: String,
  contury: String,
  city: String,
  avatarUrl: String,
  role: {
    type: String,
    default: 'user',
    required: true
  },
  meta: {
    createAt: {
      type: Date,
      default: Date.now()
    },
    updateAt: {
      type: Date,
      default: Date.now()
    }
  }
})

UserSchema.virtual('isLocked').get(function() {
  return !!(this.lockTime && this.lockTime > Date.now())
})

UserSchema.pre('save', function(next) {
  if (this.isNew) {
    this.meta.createAt = this.meta.updateAt = Date.now()
  } else {
    this.meta.updateAt = Date.now()
  }
  next()
})

UserSchema.pre('save', function(next) {
  const that = this
  if (!that.isModified('password')) return next()

  bcrypt.genSalt(saltRounds, function(err, salt) {
    if (err) return next(err)
    bcrypt.hash(that.password, salt, function(err, hash) {
      if (err) return next(err)
      that.password = hash
      next()
    })
  })
})

UserSchema.methods = {
  comparePassword(_password, password) {
    return new Promise((resolve, reject) => {
      bcrypt.compare(_password, password, function(err, res) {
        resolve(res)
      })
    })
  },
  incLoginAttempts() {
    let that = this
    return new Promise((resolve, reject) => {
      if (that.lockTime && that.lockTime < Date.now()) {
        that.update({
          $set: {
            loginAttempts: 1
          },
          $unset: {
            lockTime: 1
          }
        }, err => {
          if (!err) resolve(true)
          else reject(err)
        })
      }
      let update = {
        $inc: {
          loginAttempts: 1
        }
      }
      if (that.loginAttempts + 1 >= MAX_LOGIN_AttAMPTS && !that.isLocked) {
        update.$set = {
          lockTime: Date.now() + LOCK_TIEM
        }
      }
      that.update(update, err => {
        if (!err) resolve(true)
        else reject(err)
      })
    })
  }
}

mongoose.model('User', UserSchema)